﻿using Sliver.Core;
using Sliver.Roadnet.Components;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Sliver.Roadnet.RawInfo;
using UnityEngine;
using static Sliver.Core.SliverEngineBridge;
using Object = UnityEngine.Object;

namespace Sliver.Roadnet
{
    public class RoadnetManager
    {
        public readonly RoadnetEntity RoadnetEntity;
        
        // 车辆信息共享内存
        protected IntPtr RunningVehicles;

        // 删除车辆缓存共享内存
        protected IntPtr RemovedVehicles;

        // 车道信息共享内存
        // protected IntPtr LaneVehicleCountBuffer;

        // 交叉口信息共享内存
        protected IntPtr RawIntersections;
        
        protected IntPtr RawLanes;

        protected Dictionary<int, VehicleEntity> AllVehicles = new Dictionary<int, VehicleEntity>();
        public int AllVehicleCount => AllVehicles.Count;

        protected static int PtrSize = Marshal.SizeOf<IntPtr>();
        protected static int VehicleRawSize = Marshal.SizeOf<VehicleRawInfo>();
        protected static int RawIntersectionInfoSize = Marshal.SizeOf<RawIntersectionInfo>();

        public readonly Transform VehicleParent;


        public RoadnetManager(string configPath, MemoryInfo memoryInfo, Transform cameraCenter, Transform vehicleParent)
        {
            GameObject roadnet = new GameObject("Roadnet");
            roadnet.transform.position = Vector3.zero;

            // 初始化路网
            RoadnetEntity = new RoadnetEntity(configPath, memoryInfo, cameraCenter, roadnet.transform);
            // // 共享存储区
            // RunningVehicles = Marshal.AllocHGlobal(VehicleRawSize * MaxVehicleCount);
            // RemovedVehicles = Marshal.AllocHGlobal(VehicleRawSize * MaxVehicleCount);
            // // 等待RoadnetEntity先初始化
            // LaneVehicleCountBuffer = Marshal.AllocHGlobal(Marshal.SizeOf<int>() * RoadnetEntity.LaneInfoList.Count);

            // MemoryInfo memoryInfo = new MemoryInfo
            // {
            //     running_buffer = RunningVehicles,
            //     removed_buffer = RemovedVehicles,
            //     lane_count_buffer = LaneVehicleCountBuffer
            // };
            // // 设置共享内存空间
            // SliverEngineBridge.SystemSetMemoryBuffer(memoryInfo);

            RunningVehicles = memoryInfo.running_buffer;
            RemovedVehicles = memoryInfo.removed_buffer;
            // LaneCount = memoryInfo.lane_count;
            RawIntersections = memoryInfo.raw_intersections;
            RawLanes = memoryInfo.raw_lanes;

            VehicleParent = vehicleParent;
        }

        protected VehiclesUpdateInfo UpdateInfo;

        protected void UpdateVehicles(VehiclesUpdateInfo info)
        {
            UpdateInfo = info;
            // Debug.Log(count);
            for (int i = 0; i < info.running_count; i++)
            {
                VehicleRawInfo vr = Marshal.PtrToStructure<VehicleRawInfo>(RunningVehicles + i * VehicleRawSize);
                VehicleEntity vehicle;
                if (!AllVehicles.ContainsKey(vr.id))
                {
                    vehicle = VehicleEntity.CreateInstance(VehicleParent);
                    vehicle.ID = vr.id;
                    AllVehicles.Add(vr.id, vehicle);
                }
                else
                {
                    vehicle = AllVehicles[vr.id];
                }
                vehicle.MakeMove(new Vector3(vr.position.x, 0, vr.position.y));
            }

            for (int i = 0; i < info.remove_count; i++)
            {
                VehicleRawInfo vr = Marshal.PtrToStructure<VehicleRawInfo>(RemovedVehicles + i * VehicleRawSize);

                if (!AllVehicles.ContainsKey(vr.id))
                {
                    Debug.LogWarning($"vehicle with id {vr.id} not found!");
                    continue;
                }

                Object.Destroy(AllVehicles[vr.id].gameObject);
                AllVehicles.Remove(vr.id);
            }

            // RunningVehicleCount.text = $"运行车辆总数：{AllVehicles.Count}";
            // InstantiateVehicleCount.text = $"实例化车辆总数：{VehicleParent.childCount}";
        }

        public void NextStep()
        {
            VehiclesUpdateInfo updateInfo = SliverEngineBridge.NextStep();
            UpdateVehicles(updateInfo);

            RoadnetEntity.Update();
        }

        public RawIntersectionInfo GetRawIntersectionInfo(int index)
        {
            index %= RoadnetEntity.IntersectionInfoList.Count;
            IntPtr ptr = Marshal.PtrToStructure<IntPtr>(RawIntersections + index * PtrSize);
            return Marshal.PtrToStructure<RawIntersectionInfo>(ptr);
        }

        public RawLaneJsonData GetRaidLaneInfo(int index)
        {
            index %= RoadnetEntity.IntersectionInfoList.Count;
            IntPtr ptr = Marshal.PtrToStructure<IntPtr>(RawLanes + index * PtrSize);
            return Marshal.PtrToStructure<RawLaneJsonData>(ptr);
        }

        public int GetVehicleCount()
        {
            return UpdateInfo.running_count;
        }

        public List<VehicleRawInfo> GetVehicles()
        {
            List<VehicleRawInfo> vehicles = new List<VehicleRawInfo>();
            for (int i = 0; i < UpdateInfo.running_count; i++)
            {
                VehicleRawInfo vr = Marshal.PtrToStructure<VehicleRawInfo>(RunningVehicles + i * VehicleRawSize);
                vehicles.Add(vr);
            }

            return vehicles;
        }

        public Dictionary<int, OutputVehicleInfo> GetRunningVehiclesMap()
        {
            Dictionary<int, OutputVehicleInfo> vehicles = new Dictionary<int, OutputVehicleInfo>();
            for (int i = 0; i < UpdateInfo.running_count; i++)
            {
                VehicleRawInfo vr = Marshal.PtrToStructure<VehicleRawInfo>(RunningVehicles + i * VehicleRawSize);
                vehicles.Add(vr.id, new OutputVehicleInfo(vr));
            }

            return vehicles;
        }

        public RoadnetSnap GetSnap()
        {
            RoadnetSnap snap = new RoadnetSnap();
            snap.is_running = IsRunning();
            snap.vehicle_count = GetVehicleCount();
            SliverEngineBridge.UpdateLaneInfo();
            snap.lane_vehicle_count = RoadnetEntity.GetLaneInfos();
            snap.all_vehicles = GetRunningVehiclesMap();

            return snap;
        }

        public bool IsRunning()
        {
            return true;
        }

        public int LaneCount => RoadnetEntity.LaneInfoList.Count;

        // public Dictionary<int, int> GetLaneVehicleCount()
        // {
        //     SliverEngineBridge.UpdateLaneInfo();
        //     Dictionary<int, int> result = new Dictionary<int, int>();
        //     int index = 0;
        //     foreach (RawLaneJsonData laneInfo in RoadnetEntity.LaneInfoList)
        //     {
        //         // return belongRoad->getId() + '_' + std::to_string(getLaneIndex());
        //         int count = Marshal.PtrToStructure<int>(LaneVehicleCountBuffer + index * sizeof(int));
        //         result.Add(index, count);
        //         index++;
        //     }
        //     return result;
        // }
    }

    public class RoadnetSnap
    {
        public bool is_running;
        public int vehicle_count;
        public Dictionary<int, RawDrivableInfo> lane_vehicle_count;
        public Dictionary<int, OutputVehicleInfo> all_vehicles;
        public Dictionary<int, int> lane_waiting_vehicle_count;
    }
}